// arch-tag: 7368da1c-b5bd-4f85-abee-e3304f75c255
package de.yvert.jingle.help;

import java.io.DataOutput;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteOrder;

/**
 * An <code>OutputStream</code> that can change the byte order. Kind of like
 * <code>OutputStream</code> crossed with <code>DataOutput</code> and
 * <code>java.nio.ByteOrder</code>.
 * <p>
 * TODO: Kick the &#(*&!^ <code>java.nio</code>-Programmers.
 * 
 * @author Ulf Ochsenfahrt
 */
public class ConverterOutputStream extends FilterOutputStream implements DataOutput
{

public static final ByteOrder BIG_ENDIAN = ByteOrder.BIG_ENDIAN;
public static final ByteOrder LITTLE_ENDIAN = ByteOrder.LITTLE_ENDIAN;

protected int count;
protected ByteOrder order;

public ConverterOutputStream(ByteOrder order, OutputStream out)
{
	super(out);
	this.order = order;
}

public ConverterOutputStream(OutputStream out)
{ this(BIG_ENDIAN, out); }

public int getCount()
{ return count; }

public void setByteOrder(ByteOrder order)
{ this.order = order; }

public ByteOrder getByteOrder()
{ return order; }

@Override
public void flush() throws IOException
{ out.flush(); }

@Override
public void write(int v) throws IOException
{
	this.out.write(v);
	count++;
}

@Override
public void write(byte b[], int off, int len) throws IOException
{
	out.write(b, off, len);
	count += len;
}

public void writeBoolean(boolean v) throws IOException
{ write(v ? 1 : 0); }

public void writeByte(int v) throws IOException
{ write((byte) v); }

@SuppressWarnings("unused")
public void writeBytes(String s) throws IOException
{ throw new UnsupportedOperationException("Not implemented!"); }

public void writeChar(int v) throws IOException
{ writeShort((short) v); }

@SuppressWarnings("unused")
public void writeChars(String s) throws IOException
{ throw new UnsupportedOperationException("Not implemented!"); }

public void writeDouble(double v) throws IOException
{ writeLong(Double.doubleToLongBits(v)); }

public void writeFloat(float v) throws IOException
{ writeInt(Float.floatToIntBits(v)); }

public void writeInt(int v) throws IOException
{
	if (order == BIG_ENDIAN)
	{
		writeByte(v >> 24);
		writeByte(v >> 16);
		writeByte(v >> 8);
		writeByte(v);
	}
	else
	{
		writeByte(v);
		writeByte(v >> 8);
		writeByte(v >> 16);
		writeByte(v >> 24);
	}
}

public void writeLong(long v) throws IOException
{
	if (order == BIG_ENDIAN)
	{
		writeInt((int) (v >> 32));
		writeInt((int) v);
	}
	else
	{
		writeInt((int) v);
		writeInt((int) (v >> 32));
	}
}

public void writeShort(int v) throws IOException
{
	if (order == BIG_ENDIAN)
	{
		writeByte(v >> 8);
		writeByte(v);
	}
	else
	{
		writeByte(v);
		writeByte(v >> 8);
	}
}

@SuppressWarnings("unused")
public void writeUTF(String str) throws IOException
{ throw new RuntimeException("Not implemented!"); }

}
